﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NamedBinaryTag
{
	/// <summary>
	/// A set of Helper methods.
	/// </summary>
	internal static class TagHelper
	{
		internal static CompressionType DetermineCompression(System.IO.Stream stream)
		{
			if (!stream.CanSeek)
				throw new ArgumentException("The Stream must be Seekable.", "stream");
			stream.Position = 0;
			try
			{
				using (System.IO.Stream wrapper = WrapGZip(stream))
				{
					wrapper.ReadByte();
				}
				return CompressionType.GZip;
			}
			catch (Ionic.Zlib.ZlibException)
			{
			}
			finally
			{
				stream.Position = 0;
			}
			try
			{
				using (System.IO.Stream wrapper = WrapZLib(stream))
				{
					wrapper.ReadByte();
				}
				return CompressionType.Zlib;
			}
			catch (Ionic.Zlib.ZlibException)
			{
			}
			finally
			{
				stream.Position = 0;
			}
			return CompressionType.None;
		}

		internal static System.IO.Stream WrapHeadered(System.IO.Stream stream)
		{
			return new HeaderedStream(stream);
		}

		internal static System.IO.Stream WrapGZip(System.IO.Stream stream)
		{
			return new Ionic.Zlib.GZipStream(stream, Ionic.Zlib.CompressionMode.Decompress, true);
		}

		private static byte[] zlibBuf = new byte[2];

		internal static System.IO.Stream WrapZLib(System.IO.Stream stream)
		{
			// return new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Decompress, true);
			stream.Read(zlibBuf, 0, zlibBuf.Length);
			return new Ionic.Zlib.DeflateStream(stream, Ionic.Zlib.CompressionMode.Decompress, true);
		}
	}

	/// <summary>
	/// Defines the available compression types.
	/// </summary>
	public enum CompressionType : byte
	{
		/// <summary>
		/// No compression.
		/// </summary>
		None = 0,
		/// <summary>
		/// GZip compression.
		/// </summary>
		GZip = 1,
		/// <summary>
		/// Zlib compression.
		/// </summary>
		Zlib = 2
	}
}
